package page;


import analysisAndCode.Target;
import entity.SameQuaternion;
import entity.Word;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Orientation;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.MenuItem;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.TextArea;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import analysisAndCode.Lex;
import analysisAndCode.Parser;
import analysisAndCode.Semantic;
import entity.SymbolTable;
import utils.TokenUtil;

import java.awt.*;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.List;

public class CCompilerGUI extends Application {

    ListView<Integer> lineNumberView;
    TextArea sourceCodeArea;
    List<Word> wordList;
    List<Word> wrongWordList;
    ListView<String> fileList;
    // 词法分析结果
    TextArea analysisArea;
    TextArea resultArea;
    MenuBar menuBar;
    BorderPane borderPane;
    FileChooser fileChooser;


    javafx.scene.text.Font font = new javafx.scene.text.Font("黑体",20);

    @Override
    public void start(Stage primaryStage) {

        //获取系统工具包， 当前屏幕分辨率
        Toolkit toolkit = Toolkit.getDefaultToolkit();
        Dimension screen = toolkit.getScreenSize();

        createPane();

        Scene scene = new Scene(borderPane, screen.width * 0.9, screen.height * 0.8);
        primaryStage.setTitle("C语言编译器");
        primaryStage.setScene(scene);

        primaryStage.show();

    }

    public void createPane(){
        borderPane = new BorderPane();
        createMenu();
        borderPane.setTop(menuBar);
        borderPane.setCenter(center());
    }

    public SplitPane center(){
        SplitPane c = new SplitPane();
        c.setOrientation(Orientation.HORIZONTAL);
        c.getItems().addAll(createCenterPane(), createRightPane());
        c.setDividerPositions( 0.5, 0.5);
        return c;
    }

    private SplitPane createLeftPane() {
        SplitPane leftPane = new SplitPane();
        // 设置SplitPane方向为垂直分割
        leftPane.setOrientation(Orientation.HORIZONTAL);

        // 左侧文件列表，设置可调整大小
        fileList = new ListView<>();
        fileList.setPlaceholder(new Label("最近的文件"));

        leftPane.getItems().addAll(fileList);

        return leftPane;
    }

    private SplitPane createRightPane() {
        SplitPane rightPane = new SplitPane();
        // 设置SplitPane方向为垂直分割
        rightPane.setOrientation(Orientation.VERTICAL);

        analysisArea = new TextArea();
        analysisArea.setEditable(false);
        analysisArea.setPromptText("语法分析信息...");
        analysisArea.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
        analysisArea.setFont(font);
        resultArea = new TextArea();
        resultArea.setEditable(false);
        resultArea.setPromptText("语法分析结果...");
        resultArea.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
        resultArea.setFont(font);

        rightPane.getItems().addAll(analysisArea, resultArea);
        return rightPane;
    }

    private SplitPane createCenterPane() {

        // 创建一个垂直布局容器来同时容纳行号和代码区域
        SplitPane centerPane = new SplitPane();

        ScrollPane linePane = new ScrollPane();
        // 创建行号ListView
        lineNumberView = new ListView<>();
        lineNumberView.setFocusTraversable(false);
        lineNumberView.setMaxWidth(70); // 行号宽度可根据需要调整
        lineNumberView.setPrefHeight(Double.MAX_VALUE); // 设置ListView的高度为最大值
        linePane.setContent(lineNumberView);
        linePane.setMaxWidth(40);
        linePane.setFitToHeight(true); // 让ScrollPane垂直方向充满centerPane

        // 中间代码编辑区
        sourceCodeArea = new TextArea();
        sourceCodeArea.setPromptText("请输入或打开C语言源代码...");
        sourceCodeArea.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
        sourceCodeArea.textProperty().addListener((observable, oldValue, newValue) -> updateLineNumbers(newValue));
        sourceCodeArea.setFont(font);

        lineNumberView.setFixedCellSize(font.getSize() * 1.37); // 设置行高，加上一些额外空间

        // 监听ScrollPane的垂直滚动位置变化，手动设置ListView的滚动位置
        sourceCodeArea.scrollTopProperty().addListener((observable, oldValue, newValue) -> {
            lineNumberView.setTranslateY(-newValue.doubleValue());
        });

        // 根据sourceCodeArea的字体大小动态计算ListView的行高
        sourceCodeArea.fontProperty().addListener((observable, oldValue, newValue) -> {
            javafx.scene.text.Font sourceFont = newValue;
            lineNumberView.setFixedCellSize(sourceFont.getSize() * 1.37); // 设置行高，加上一些额外空间
        });

        centerPane.getItems().addAll(linePane, sourceCodeArea);
        return centerPane;
    }

    private void updateLineNumbers(String text) {
        ObservableList<Integer> numbers = FXCollections.observableArrayList();
        String[] lines = text.split("\n", -1); // -1保留末尾的空行
        for (int i = 1; i <= lines.length; i++) {
            numbers.add(i);
        }
        lineNumberView.setItems(numbers);
    }

    private void createMenu() {

        menuBar = new MenuBar();

        // 二级菜单
        Menu fileMenu = new Menu("文件");
        MenuItem openItem = new MenuItem("打开");
        openItem.setOnAction(e -> handleOpenFile());
        MenuItem saveItem = new MenuItem("保存");
        //打开文件事件
        fileMenu.getItems().addAll(openItem, saveItem);

        Menu editMenu = new Menu("编辑");
        MenuItem copyItem = new MenuItem("复制");
        editMenu.getItems().addAll(copyItem);

        Menu viewMenu = new Menu("视图");
        MenuItem recentFilesItem = new MenuItem("最近的文件");
        viewMenu.getItems().addAll(recentFilesItem);

        Menu analyzeMenu = new Menu("分析");
        MenuItem lexicalItem = new MenuItem("词法分析");
        MenuItem grammarItem = new MenuItem("语法分析");
        MenuItem semanticItem = new MenuItem("语义分析");
        analyzeMenu.getItems().addAll(lexicalItem, grammarItem, semanticItem);
        lexicalItem.setOnAction(e -> handLexical());
        grammarItem.setOnAction(e -> handParse());
        semanticItem.setOnAction(e -> handSemantic());

        Menu codeMenu = new Menu("代码");
        MenuItem mediateCodeItem = new MenuItem("中间代码");
        MenuItem targetCodeItem = new MenuItem("目标代码生成");
        MenuItem algorithmsItem = new MenuItem("相关算法");
        codeMenu.getItems().addAll(mediateCodeItem, targetCodeItem, algorithmsItem);
        mediateCodeItem.setOnAction(e -> handMediateCode());
        targetCodeItem.setOnAction(e -> handTargetCode());

        Menu otherMenu = new Menu("其他");
        MenuItem exportImageItem = new MenuItem("导出图片");
        otherMenu.getItems().addAll(exportImageItem);


        // 处理菜单项点击事件
        saveItem.setOnAction(e -> handleSaveFile());
        copyItem.setOnAction(e ->handleCopy());

        menuBar.getMenus().addAll(fileMenu, editMenu, viewMenu, analyzeMenu, codeMenu, otherMenu);
    }

    private void handLexical() {
        String text = sourceCodeArea.getText();
        Lex lex = new Lex();
        lex.OnLex(text);
        if(wordList != null){
            wordList.clear();
        }
        wordList = lex.getWordList();
        wrongWordList = lex.getWrongWordList();
        text = "行号" + "\t\t"
                + "类型" + "\t\t"
                + "种别码" + "\t\t"
                + "单词" + "\n";
        for (int i = 0; i < wordList.size(); i++) {
            text += wordList.get(i).getLine() + "\t\t"
                    + TokenUtil.getTokenType(wordList.get(i).getCode()) + "\t\t"
                    + wordList.get(i).getCode() + "\t\t"
                    + wordList.get(i).getWord() + "\n";
        }
        int m = 0;
        for (Word word : wordList) {
            System.out.println(m + " " + word.toString());
            m++;
        }
        analysisArea.setText(text);
        String wrong = "";
        for (int i = 0; i < wrongWordList.size(); i++) {
            System.out.println(wrongWordList.get(i).toString());
            wrong += "错误在第 " + wrongWordList.get(i).getLine() + " 行, 错误单词为 " + wrongWordList.get(i).getWord() + "\n";
        }
        resultArea.setText(wrong);
    }

    private void handParse(){
        // 先进行词法分析
        handLexical();
        // 手动语法分析
        Parser parser = new Parser(wordList);
        parser.parser();
        // 获取语法树
        String syntaxTree = parser.getSyntaxTree();
        analysisArea.setText(syntaxTree);
        // 获取错误信息
        String syntaxError = parser.getSyntaxError();
        resultArea.setText(syntaxError);
    }

    private void handSemantic(){
        // 先进行词法分析
        handLexical();
        // 手动语义分析
        Semantic semantic = new Semantic(wordList);
        semantic.parser();
        // 获取符号表
        SymbolTable symbolTable = semantic.getSymbolTable();
        analysisArea.setText(
                symbolTable.printConstList() + "\n" +
                        symbolTable.printVariableList() + "\n" +
                        symbolTable.printFunctionList()
        );
        // 获取错误信息
        String semanticError = semantic.getSemanticError();
        resultArea.setText(semanticError);
    }
    private void handTargetCode(){
        // 先进行词法分析
        handLexical();
        // 语法分析和中间代码生成
        Semantic semantic = new Semantic(wordList);
        semantic.parser();
        // 获取符号表
        SymbolTable symbolTable = semantic.getSymbolTable();
        // 获取中间代码
        List<SameQuaternion> quaternionList = semantic.getSameQuaternionList();
        String text = "";
        for (int i = 0; i < quaternionList.size(); i++) {
            text += i + "\t( ";
            text += quaternionList.get(i).getOperate() + ", ";
            text += quaternionList.get(i).getOperate1() + ", ";
            text += quaternionList.get(i).getOperate2() + ", ";
            text += quaternionList.get(i).getResult() + " )\n";
        }
        analysisArea.setText(text);
        // 目标代码
        Target target = new Target(quaternionList, symbolTable, semantic.getFunctionScope());
        target.target();
        resultArea.setText(target.getAssemblyCode());
    }

    private void handMediateCode(){
        // 先进行词法分析
        handLexical();
        // 语法分析和中间代码生成
        Semantic semantic = new Semantic(wordList);
        semantic.parser();
        // 获取符号表
        SymbolTable symbolTable = semantic.getSymbolTable();
        resultArea.setText(
                symbolTable.printConstList() + "\n" +
                        symbolTable.printVariableList() + "\n" +
                        symbolTable.printFunctionList()
        );
        // 获取中间代码
        List<SameQuaternion> quaternionList = semantic.getSameQuaternionList();
        String text = "";
        for (int i = 0; i < quaternionList.size(); i++) {
            text += i + "\t( ";
            text += quaternionList.get(i).getOperate() + ", ";
            text += quaternionList.get(i).getOperate1() + ", ";
            text += quaternionList.get(i).getOperate2() + ", ";
            text += quaternionList.get(i).getResult() + " )\n";
//            text += i +"\t\t";
//            text += quaternionList.get(i).getOperate() + "\t\t";
//            if (quaternionList.get(i).getOperate1() != null){
//                text += quaternionList.get(i).getOperate1().getName() + "(" + quaternionList.get(i).getOperate1().getVal()+ ")";
//            }else{
//                text += quaternionList.get(i).getOperate1();
//            }
//            text += "\t\t";
//            if (quaternionList.get(i).getOperate2() != null){
//                text += quaternionList.get(i).getOperate2().getName() + "(" + quaternionList.get(i).getOperate2().getVal() + ")";
//            }else{
//                text += quaternionList.get(i).getOperate2();
//            }
//            text += "\t\t";
//            text += quaternionList.get(i).getResult() + "\n";
        }
        analysisArea.setText(text);
    }

    private void handleCopy() {
        System.out.println(1);
    }


    // 模拟文件操作方法
    private void handleOpenFile() {
        fileChooser = new FileChooser();
        // 实际操作将打开文件对话框并读取文件内容
        fileChooser.setInitialDirectory(new File("."));
        File selectedFile = fileChooser.showOpenDialog(new Stage());
        if (selectedFile != null) {
            try (BufferedReader reader = new BufferedReader(new FileReader(selectedFile))) {
                StringBuilder content = new StringBuilder();
                String line;
                while ((line = reader.readLine()) != null) {
                    content.append(line).append("\n");
                }
                sourceCodeArea.setText(content.toString());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private static void handleSaveFile() {
        // 实际操作将保存当前sourceCodeArea中的内容到文件
    }



    public static void main(String[] args) {
        launch(args);
    }
}
